﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using JF.RealtimeNotifications.Notifiers.Extensibility;
using System.Net;
using System.Data;
using System.Threading.Tasks;
using System.Threading;
using System.Xml.Linq;
using System.IO;
using System.ServiceModel.Syndication;
using System.Xml;

namespace JF.RealtimeNotifications.Notifiers.Feeds
{
    public class FeedsNotifier : ISubscriberNotifier
    {
        private class FeedNotificationInfo
        {
            public FeedNotificationInfo()
            {
                LastUpdate = DateTime.MinValue;
            }

            public Notification Notification { get; set; }
            public OnNotificationDelegate OnNotification { get; set; }
            public DateTime LastUpdate { get; set; }
        }

        public int FeedPollingTime { get; set; }

        private List<FeedNotificationInfo> subscriptions;
        private bool isConnected;

        public void Subscribe(Notification notification, OnNotificationDelegate onNotification)
        {
            subscriptions.Add(new FeedNotificationInfo()
            {
                Notification = notification,
                OnNotification = onNotification
            });
        }

        public void Connect(OnConnectDelegate callback)
        {
            if (FeedPollingTime < 5)
            {
                FeedPollingTime = 5;
            }

            subscriptions = new List<FeedNotificationInfo>();
            isConnected = true;

            new Task(() => {
                while (isConnected)
                {
                    foreach (var subscription in subscriptions)
                    {
                        var feedItems = ReadFeed(subscription);

                        foreach (var item in feedItems)
                        {
                            var notification = new FeedNotification(subscription.Notification.Title, item);

                            subscription.OnNotification(notification);
                        }
                    }

                    Thread.Sleep(FeedPollingTime * 1000);
                }
            }).Start();

            if (callback != null)
            {
                callback(null);
            }
        }

        private static List<FeedItem> ReadFeed(FeedNotificationInfo subscription)
        {
            var url = subscription.Notification.Text;
            var existUpdates = false;

            //create a new list of the rss feed items to return
            List<FeedItem> result = new List<FeedItem>();

            XmlReader reader = XmlReader.Create(url);
            SyndicationFeed feed = SyndicationFeed.Load(reader);

            if (feed.LastUpdatedTime != null)
            {
                existUpdates = subscription.LastUpdate < feed.LastUpdatedTime.DateTime;
                subscription.LastUpdate = feed.LastUpdatedTime.DateTime;
            }

            if (existUpdates)
            {
                foreach (var item in feed.Items)
                {
                    result.Add(new FeedItem()
                    {
                        Title = item.Title.Text,
                        PublishDate = item.PublishDate.DateTime,
                        Description = item.Summary == null ? String.Empty : item.Summary.Text,
                        Link = item.Links.FirstOrDefault() == null ? String.Empty : item.Links.FirstOrDefault().Uri.OriginalString
                    });
                }
            }

            //return the rss feed items
            return result;
        }
    }
}
